package com.googlecode.sere.http

import com.googlecode.sere.util.Logging
import com.googlecode.sere.translation.MediaRange
import com.googlecode.sere.method.HttpWritable

abstract class HttpException(val code: Status.Value, val message: String = "")
  extends Exception(message) with HttpWritable with Logging {

	def writeToHttpResponse(res: HttpResponse) {
    logger.debug("Setting response status to {}", code)
		res.setStatus(code.id)
    res.setEntityContent(message.getBytes)
	}
}

class NotFound extends HttpException(Status.NotFound)

class MethodNotAllowed(allowed: Seq[String] = Seq())
  extends HttpException(Status.MethodNotAllowed) {
    
  override def writeToHttpResponse(res: HttpResponse) {
    super.writeToHttpResponse(res)
    res.setHeader("Accept", allowed.mkString(", "))
	}
}

class NotImplemented(msg: String) extends HttpException(Status.NotImplemented, msg)

class BadRequest(msg: String) extends HttpException(Status.BadRequest, msg)

class InternalError extends HttpException(Status.InternalError)

class NotAcceptable(msg: String) extends HttpException(Status.NotAcceptable, msg)

/**
 * HTTP does not mandate content negotiation for entities sent in PUT and POST requests.
 * However, an Accept header sent in case of an Unsupported Media Type response won't hurt,
 * and in fact is the approach taken by the (HTTP inspired) SI(P) protocol
 * {@link http://tools.ietf.org/html/rfc3261#section-21.4.13}
 */
class UnsupportedMediaType(val supported: Set[MediaRange])
  extends HttpException(Status.UnsupportedMediaType) {
    
  override def writeToHttpResponse(res: HttpResponse) {
    super.writeToHttpResponse(res)
    res.setHeader("Accept", supported.toString)
	}
}

class Unauthorized extends HttpException(Status.Unauthorized) 